<?php
/*
 * @Description    : 消息推送任务
 * @Version        : 1.0.0
 * @Author         : QianLong
 * @Date           : 2020-01-22 15:56:35
 * @LastEditors    : QianLong
 * @LastEditTime   : 2024-01-16 17:02:36
 */

declare(strict_types=1);

namespace App\Job;

use Hyperf\AsyncQueue\Job;

class PushSendJob extends Job
{
    public $params;
    public $redisCache;

    public function __construct($params, $redisCache)
    {
        $this->params = $params;
        $this->redisCache = $redisCache;
    }

    public function handle()
    {
        if (!empty($this->params) && is_array($this->params)) {
            $serverInfo = $this->redisCache->getPushServer($this->params['ps_id']);
            $pushSetting = $this->redisCache->getPushSetting($this->params['uid']);

            \Hyperf\Retry\Retry::whenReturns(false) // 当返回false时重试
                ->max(2) // 最多5次
                ->inSeconds(30 * 60) // 最长30*60秒
                ->sleep(15 * 1000) // 间隔30秒
                ->fallback(function () use ($pushSetting, $serverInfo) {
                    return $this->doSend($pushSetting, $serverInfo);
                }) // fallback函数
                ->call(function () use ($pushSetting, $serverInfo) {
                    return $this->doSend($pushSetting, $serverInfo);
                });

            unset($pushSetting, $serverInfo);
        }
    }
    public function doSend($pushSetting, $serverInfo)
    {
        if (empty($this->params['single_cid'])) {
            return true;
        }
        $collection = mongodb2()->selectCollection('send_push_log_' . $this->params['uid']);
        if (isset($this->params['psl_id']) && !empty($this->params['psl_id'])) {
            $postData['_id'] = $this->params['psl_id'];
        } else {
            $postData['_id'] = createULId('PSL');
            $postData['pt_id'] = $this->params['pt_id'];
            $postData['uid'] = $this->params['uid'];
            $postData['ps_id'] = $this->params['ps_id'];
            $postData['send_content'] = '';
            $postData['cid'] = $this->params['single_cid'];
            $params = $this->params;
            unset($params['uid'], $params['single_cid']);
            $postData['params'] = json_encode($params, JSON_UNESCAPED_UNICODE);
            unset($params);
            $postData['title'] = $this->params['title'];
            $postData['content'] = $this->params['content'];
            $postData['send_result'] = false;
            $postData['type'] = $serverInfo['type'];
            $postData['send_error'] = '';
            $postData['platform'] = $serverInfo['platform'];
            $postData['send_result_data'] = '';
            $postData['task_id'] = '';
            $postData['is_read'] = 0;
            $postData['read_time'] = 0;
            $postData['send_time'] = time();
            $postData['date'] = date('Ymd');
            $postData['hour'] = date('YmdH');
            $postData['only_hour'] = date('H') . ':00';
            $postData['hour_stamp'] = strtotime(date('Y-m-d H') . ':00:00');
            $postData['month'] = date('Ym');
            $postData['year'] = date('Y');
            // mongodb2()->send_push_log->insertOne($postData);
            $collection->insertOne($postData);
            (new \App\Service\Common)->mongodbIndexCreate($collection, 'uid_send_time', ['uid' => 1, 'send_time' => -1]);
            (new \App\Service\Common)->mongodbIndexCreate($collection, 'uid_send_time_ps_id', ['uid' => 1, 'send_time' => -1, 'ps_id' => -1]);
        }
        if (empty($serverInfo)) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '推送配置不存在或推送配置ID不正确']]);
            return true;
        }
        if ($serverInfo['status'] != 1) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '推送配置未启用']]);
            return true;
        }
        // $templateContent = $this->redisCache->getPushTemplateRealTime($this->params['pt_id']);
        // if (empty($templateContent)) {
        //     $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '推送模板不存在或推送模板ID不正确']]);
        //     return true;
        // }
        // $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['title' => $templateContent['title']]]);
        $day_limit = $this->redisCache->sendLimit($this->params['ps_id'] . ':' . $this->params['single_cid'], 'day');
        if (!empty($day_limit) && !empty($pushSetting['day_limit']) && $day_limit > $pushSetting['day_limit']) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '超过单个自然日内发送上限，发送失败']]);
            return true;
        }
        $hour_limit = $this->redisCache->sendLimit($this->params['ps_id'] . ':' . $this->params['single_cid'], 'hour');
        if (!empty($hour_limit) && !empty($pushSetting['hour_limit']) && $hour_limit > $pushSetting['hour_limit']) {
            $this->redisCache->sendLimitDec($this->params['ps_id'] . ':' . $this->params['single_cid'], 'day');
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '超过每小时内发送上限，发送失败']]);
            return true;
        }
        $minute_limit = $this->redisCache->sendLimit($this->params['ps_id'] . ':' . $this->params['single_cid'], 'minute');
        if (!empty($minute_limit) && !empty($pushSetting['minute_limit']) && $minute_limit > $pushSetting['minute_limit']) {
            $this->redisCache->sendLimitDec($this->params['ps_id'] . ':' . $this->params['single_cid'], 'hour');
            $this->redisCache->sendLimitDec($this->params['ps_id'] . ':' . $this->params['single_cid'], 'day');
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '超过每分钟内发送上限，发送失败']]);
            return true;
        }
        $result = [];
        $send_content = '';
        // $params_json_array = (!empty($this->params['params_json']))?json_decode($this->params['params_json'],true):[];
        if (isset($this->params['platform']) && !empty($this->params['platform'])) {
            $serverInfo['platform'] = $this->params['platform'];
        }
        switch ($serverInfo['platform']) {
            case 'getui':
                if ($this->params['single_cid'] == 'all') {
                    $result = (new \App\Service\Push\Getui($serverInfo))->pushAllTask($this->params);
                } else {
                    $result = (new \App\Service\Push\Getui($serverInfo))->singlePushStartPage($this->params);
                }
                break;
            case 'umeng':
                $result = (new \App\Service\Push\Umeng($serverInfo))->singlePushStartPage($this->params);
                break;
            case 'jiguang':
                $result = (new \App\Service\Push\JiGuang($serverInfo))->singlePushStartPage($this->params);
                break;
            case 'goeasy':
                $result = (new \App\Service\Push\GoEasy($serverInfo))->pushContentApp($this->params);
                break;
            default:
                # code...
                break;
        }
        if (empty($result)) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '未能获取到发送结果数据', 'send_content' => $send_content]]);
            return false;
        }
        $result['task_id'] = !isset($result['task_id'])?'': $result['task_id'];
        $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => $result['send_error'], 'pushParam' => $result['pushParam'], 'send_result' => $result['send_result'], 'send_result_data' => $result['send_result_data'], 'task_id' => $result['task_id'], 'send_content' => $send_content]]);
        unset($postData, $result, $serverInfo, $templateContent);
        if (!isset($this->params['psl_id']) || empty($this->params['psl_id'])) {
            $this->insertLog($this->params['ps_id'], $this->params['uid'], $serverInfo['platform'], $serverInfo['type']);
        }
        return true;
    }
    public function insertLog($id, $uid, $platform, $type)
    {
        $where['hour'] = date('YmdH');
        $where['ps_id'] = $id;
        $where['platform'] = $platform;
        $hasLog = mongodb2()->send_push_log_tj->findOne($where);
        if (empty($hasLog)) {
            $insert['_id'] = createULId();
            $insert['date'] = date('Ymd');
            $insert['hour'] = date('YmdH');
            $insert['only_hour'] = date('H') . ':00';
            $insert['hour_stamp'] = strtotime(date('Y-m-d H') . ':00:00');
            $insert['month'] = date('Ym');
            $insert['year'] = date('Y');
            $insert['create'] = time();
            $insert['ps_id'] = $id;
            $insert['platform'] = $platform;
            $insert['type'] = $type;
            $insert['uid'] = (int) $uid;
            $insert['sv'] = 1;
            $insert['rv'] = 0;
            mongodb2()->send_push_log_tj->insertOne($insert);
        } else {
            mongodb2()->send_push_log_tj->updateOne($where, ['$inc' => ['sv' => 1]]);
        }
    }
}
